package unitTests;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

import increment1.*;

import static org.junit.Assert.*;

import org.junit.Before;
import org.junit.Test;

/**
 * TaskUnitTests class contains the units tests of the methods in the Task class 
 * 
 * @author Rolf Schmidt
 *
 */
public class TaskUnitTests {
	
	final String H_LINE = "---------------------------------------";
	final String DATE_FORMAT = "yyyy-MM-dd";
	final int LONG_DURATION = 1548765412;
	final int LONG_STRING = 100;
	final int VERY_LONG_STRING = 2000;
	final String WILD_STRING = "*@&(|}{+?~+\\/";
	StringBuffer sbLong;
	StringBuffer sbVeryLong;
	
	@Before
	public void setUp() {
		sbLong = new StringBuffer(LONG_STRING);
		for (int i = 0; i < LONG_STRING; i++) {
			sbLong.append("a");
		}
		
		sbVeryLong = new StringBuffer(VERY_LONG_STRING);
		for (int i = 0; i < VERY_LONG_STRING; i++) {
			sbVeryLong.append("a");
		}
    }
	
	public TaskUnitTests() {
	}

	@Test
	public void testTaskConstructor() {
		Task task = new Task();
		
		assertEquals("none", task.getId());
		assertEquals("none", task.getTitle());
		assertEquals("none", task.getDescription());
		assertEquals(1, task.getDuration());
		assertEquals("none", task.getDeliverable());
		assertEquals("nobody", task.getPerson());
	}

	@Test
	public void testTaskToString1() {
		Task task = new Task();
		StringBuffer sb = new StringBuffer(H_LINE);
		Calendar testDeadline = Calendar.getInstance();

		sb.append("\nID: none");
		sb.append("\nTitle: none");
		sb.append("\nDescription: none");
		sb.append("\nDuration: 1");
		sb.append("\nDeliverable: none");

		SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
		String deadline = sdf.format(testDeadline.getTime());
		sb.append("\nDeadline: " + deadline);
		sb.append("\nPerson: nobody");
		sb.append("\n" + H_LINE + "\n");

		assertEquals(sb.toString(), task.toString());
	}

	@Test
	public void testTaskToString2() {
		Task task = new Task();
		StringBuffer sb = new StringBuffer(H_LINE);
		Calendar testDeadline = Calendar.getInstance();

		task.setId("Test task");
		task.setTitle("Test title");
		task.setDescription("Test description");
		task.setDuration(25);
		task.setDeliverable("Test deliverable");
		task.setPerson("John Doe");

		sb.append("\nID: Test task");
		sb.append("\nTitle: Test title");
		sb.append("\nDescription: Test description");
		sb.append("\nDuration: 25");
		sb.append("\nDeliverable: Test deliverable");

		SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
		String deadline = sdf.format(testDeadline.getTime());
		sb.append("\nDeadline: " + deadline);
		sb.append("\nPerson: John Doe");
		sb.append("\n" + H_LINE + "\n");

		assertEquals(sb.toString(), task.toString());
	}

	@Test
	public void testTaskEquals1() {
		Task task = new Task();
		assertTrue(task.equals(task));
	}
	
	@Test
	public void testTaskEquals2() {
		Task task1 = new Task();
		Task task2 = new Task();
		Calendar testDeadline = Calendar.getInstance();

		task1.setId("task");
		task1.setDeadline(testDeadline);
		task2.setId("task");
		task2.setDeadline(testDeadline);

		assertTrue(task1.equals(task2));
	}
	
	@Test
	public void testTaskEquals3() {
		Task task1 = new Task();
		Task task2 = new Task();

		task1.setId("task");
		task2.setId("task2");

		assertFalse(task1.equals(task2));
	}
	
	@Test
	public void testTaskEquals4() {
		Task task = new Task();

		String test = "test different object";

		assertFalse(task.equals(test));
	}
	
	@Test
	public void testTaskEquals5() {
		Task task = new Task();
		assertFalse(task.equals(null));
	}
	
	@Test
	public void testTaskEquals6() {
		Task task1 = new Task();
		Task task2 = new Task();
		Calendar testDeadline = Calendar.getInstance();

		task1.setDeadline(testDeadline);
		task2.setDeadline(testDeadline);

		task2.setId(null);
		assertTrue(task1.equals(task2));
		task2.setId("none");
		
		task2.setTitle(null);
		assertTrue(task1.equals(task2));
		task2.setTitle("none");
		
		task2.setDescription(null);
		assertTrue(task1.equals(task2));
		task2.setDescription("none");
		
		task2.setDeliverable(null);
		assertTrue(task1.equals(task2));
		task2.setDeliverable("none");
		
		task2.setDeadline(null);
		assertTrue(task1.equals(task2));
		task2.setDeadline(testDeadline);
		
		task2.setPerson(null);
		assertTrue(task1.equals(task2));
	}

	@Test
	public void testTaskSetId1() {
		Task task = new Task();
		
		task.setId("");
		assertEquals("none", task.getId());
	}
	
	@Test
	public void testTaskSetId2() {
		Task task = new Task();
		
		task.setId(sbLong.toString());
		assertEquals(sbLong.toString(), task.getId());
	}
	
	@Test
	public void testTaskSetId3() {
		Task task = new Task();

		task.setId(null);
		assertEquals("none", task.getId());
	}
	
	@Test
	public void testTaskSetId4() {
		Task task = new Task();
		
		task.setId(WILD_STRING);
		assertEquals(WILD_STRING, task.getId());
	}
	
	@Test
	public void testTaskSetTitle1() {
		Task task = new Task();
		
		task.setTitle("");
		assertEquals("none", task.getTitle());
	}
	
	@Test
	public void testTaskSetTitle2() {
		Task task = new Task();

		task.setTitle(sbLong.toString());
		assertEquals(sbLong.toString(), task.getTitle());
	}
	
	@Test
	public void testTaskSetTitle3() {
		Task task = new Task();

		task.setTitle(null);
		assertEquals("none", task.getTitle());
	}
	
	@Test
	public void testTaskSetTitle4() {
		Task task = new Task();
		
		task.setTitle(WILD_STRING);
		assertEquals(WILD_STRING, task.getTitle());
	}
	
	@Test
	public void testTaskSetDescription1() {
		Task task = new Task();
		
		task.setDescription("");
		assertEquals("none", task.getDescription());
	}
	
	@Test
	public void testTaskSetDescription2() {
		Task task = new Task();
		
		task.setDescription(sbVeryLong.toString());
		assertEquals(sbVeryLong.toString(), task.getDescription());
	}
	
	@Test
	public void testTaskSetDescription3() {
		Task task = new Task();

		task.setDescription(null);
		assertEquals("none", task.getDescription());
	}
	
	@Test
	public void testTaskSetDescription4() {
		Task task = new Task();
		
		task.setDescription(WILD_STRING);
		assertEquals(WILD_STRING, task.getDescription());
	}
	
	@Test
	public void testTaskSetDuration1() {
		Task task = new Task();
		
		task.setDuration(10);
		assertTrue(task.getDuration() > 0);
	}
	
	@Test
	public void testTaskSetDuration2() {
		Task task = new Task();
		
		task.setDuration(-10);
		assertTrue(task.getDuration() > 0);
	}
	
	@Test
	public void testTaskSetDuration3() {
		Task task = new Task();
		
		task.setDuration(0);
		assertTrue(task.getDuration() > 0);
	}
	
	@Test
	public void testTaskSetDuration4() {
		Task task = new Task();
		
		task.setDuration(LONG_DURATION);
		assertTrue(task.getDuration() > 0);
	}
	
	@Test
	public void testTaskSetDuration5() {
		Task task = new Task();
		
		task.setDuration(Integer.MAX_VALUE);
		assertTrue(task.getDuration() > 0);
	}
	
	@Test
	public void testTaskSetDeliverable1() {
		Task task = new Task();
		
		task.setDeliverable("");
		assertEquals("none", task.getDeliverable());
	}
	
	@Test
	public void testTaskSetDeliverable2() {
		Task task = new Task();

		task.setDeliverable(sbLong.toString());
		assertEquals(sbLong.toString(), task.getDeliverable());
	}
	
	@Test
	public void testTaskSetDeliverable3() {
		Task task = new Task();

		task.setDeliverable(null);
		assertEquals("none", task.getDeliverable());
	}
	
	@Test
	public void testTaskSetDeliverable4() {
		Task task = new Task();
		
		task.setDescription(WILD_STRING);
		assertEquals(WILD_STRING, task.getDescription());
	}
	
	@Test
	public void testTaskSetDeadline1() {
		Task task = new Task();
		Calendar now = Calendar.getInstance();
		Calendar testDeadline = Calendar.getInstance();

		task.setDeadline(now);
		assertTrue(task.getDeadline() instanceof Calendar);
		
		testDeadline.add(Calendar.DAY_OF_MONTH, 5);
		task.setDeadline(testDeadline);
		assertTrue(task.getDeadline() instanceof Calendar);
	}

	@Test
	public void testTaskSetDeadline2() {
		Task task = new Task();
		Calendar testDeadline = Calendar.getInstance();

		testDeadline.add(Calendar.DAY_OF_MONTH, -5);
		task.setDeadline(testDeadline);
		assertTrue(task.getDeadline() instanceof Calendar);
	}

	@Test
	public void testTaskSetDeadline3() {
		Task task = new Task();
		
		task.setDeadline(null);
		assertTrue(task.getDeadline() instanceof Calendar);
	}

	@Test
	public void testTaskSetPerson1() {
		Task task = new Task();
		
		task.setPerson("");
		assertEquals("nobody", task.getPerson());
	}
	
	@Test
	public void testTaskSetPerson2() {
		Task task = new Task();

		task.setPerson(sbLong.toString());
		assertEquals(sbLong.toString(), task.getPerson());
	}
	
	@Test
	public void testTaskSetPerson3() {
		Task task = new Task();

		task.setPerson(null);
		assertEquals("nobody", task.getPerson());
	}
	
	@Test
	public void testTaskSetPerson4() {
		Task task = new Task();
		
		task.setPerson(WILD_STRING);
		assertEquals(WILD_STRING, task.getPerson());
	}
	
	@Test
	public void testTaskFormatDate1() {
		
	    Task task = new Task();
		Calendar testDeadline = new GregorianCalendar(2200, 02, 30);
	    
		Object params[] = new Object[1];
		params[0] = testDeadline.getTime();
		
	    String s = (String) PrivateAccessor.getPrivateMethod(task, "formatDate", params);
	    assertEquals (s, "2200-03-30");
	}
	
	@Test
	public void testTaskFormatDate2() {
		Task task = new Task();
		Calendar testDeadline = new GregorianCalendar(2000, 0, 1);
		
		Object params[] = new Object[1];
		params[0] = testDeadline.getTime();
		
	    String s = (String) PrivateAccessor.getPrivateMethod(task, "formatDate", params);
	    assertEquals (s, "2000-01-01");
	}
	
	@Test
	public void testTaskFormatDate3() {
		Task task = new Task();
		
		Object params[] = new Object[1];
		params[0] = null;
		
	    String s = (String) PrivateAccessor.getPrivateMethod(task, "formatDate", params);
	    assertTrue(s.equals(""));
	}
}
